Many computer programs are created using high-level source programming languages that have English-like syntax. However, a computer cannot directly execute the source text of the program expressed in such languages (“source code”). Instead, two main approaches are used to transform the source code into machine-executable code. In one approach, known as compilation, the source code is provided to a compiler, which parses the source code, carries out lexical analysis and syntax analysis, and generates machine-executable object code for later execution. Often such analysis and code generation requires the processor to make multiple passes through the source code. One disadvantage of this approach is that the compiled code typically is executable using only one processor type or processor family; a second disadvantage is that a processor must carry out the entire compilation process before it can begin executing the code. Examples of languages that use this approach are C and C++.
In a second approach, known as interpretation, the source code is provided to an interpreter. In interpretation, two sub-approaches are generally used. In the “pure interpretation” approach, there is no visible intermediate code processing stage; the program code requires no special pre-processing and is received as-is by the interpreter, which interprets it directly. Examples of such languages are PERL® and JavaScript®.
In the other sub-approach, the source code is converted to an intermediate code representation, which is then interpreted. For example, in a first phase of operation, the interpreter makes a single pass over the source code and converts each source code instruction into one or more corresponding intermediate language instructions. In a second phase of operation, the interpreter executes the intermediate language instructions. An example of a computer language that uses this approach is JAVA®, developed by Sun Microsystems, Inc.; in JAVA the intermediate language consists of “byte codes” that are executed, at run time, by a JAVA Virtual Machine. The source program code is first compiled into intermediate language instructions represented in byte codes. The interpreter takes the pre-processed code and translates it into specific low-level operating system instructions on the fly.
An advantage of this approach is that a JAVA Virtual Machine that is compatible with a particular processor family can directly execute any JAVA program, without the need for a compilation stage. However, the JAVA interpretation approach also has disadvantages. For example, every time a JAVA application is started, the JAVA Virtual Machine must first start executing. Unfortunately, there are costs associated with startup of the JAVA Virtual Machine, in terms of time, memory and processor resources, which degrade startup performance of the application. These startup costs include the allocation of memory, the creation of internal data structures, and the initialization of these structures. Collectively these processes impose significant and undesirable overhead.
In some contexts, the performance degradation associated with these startup costs is significant. The problem is especially evident when the expected running time of the program is small and the program is invoked frequently over a period of time. In such scenarios, the startup time of the application can become as resource-intensive and time consuming as running the program itself.
For example, one problem involved in interpretation of JAVA programs relates to development of large, complex computer application programs. Development of such programs, e.g., by professional software engineers, may involve creating numerous individual programs and then combining them into the complete application. The engineers may have thousands or tens of thousands of source code elements in various files or directories. During the course of software development, engineers have to compile an entire application often to verify that it compiles and works correctly. This compilation process is often accomplished with the use of scripts called “makefiles,” and in a typical approach this involves running the JAVA compiler repetitively for each directory that contains source code files. However, because the Sun Microsystems JAVA compiler is written in the JAVA language and therefore executes in the JAVA Virtual Machine, every time the JAVA compiler is started, the JAVA Virtual Machine is started again. This results in unacceptable overhead and inefficient startup throughout the compilation process.
As another example, the UNIX operating environment consists of many small programs each dedicated to specific purpose. For example, a program that implements the command “1s” prints the list of files in the directory. This command carries out a simple task and is expected to execute fast. However, implementation of a program of the nature of “ls” as a JAVA program is presently impractical because the overhead of starting the JAVA Virtual Machine is larger than the time or other resources needed to execute the program itself. Thus, there is a need for a way to write programs in JAVA that would otherwise be impractical.
Several past attempts have been made to solve this problem. One approach is known as SpeedyCGI, and provides a way of running Common Gateway Interface (CGI) PERL scripts persistently. SpeedyCGI is described in the “daemoninc” dot corn Web site. After a PERL script is initially run, instead of exiting, SpeedyCGI keeps the PERL interpreter in memory. During subsequent runs, the interpreter is used to handle new requests, instead of starting a new PERL interpreter for each execution.
However, SpeedyCGI has many limitations and drawbacks. For example, SpeedyCGI requires modification and recompilation of the interpreter environment. This also means that SpeedyCGI has to be recompiled for every different version or release of the PERL interpreter. This approach is not readily adaptable to other environments, such as the JAVA programming environment, in which the developer of JAVA (Sun Microsystems) places contractual restrictions on re-distribution of modified JAVA Virtual Machine implementations.
Also, SpeedyCGI is restricted to running on one machine. Since SpeedyCGI is restricted to running on one machine, it cannot utilize resources from multiple machines. All resources must reside on the same machine as the client and the server. Furthermore, it currently only operates on selected computer platforms.
Additional known disadvantages of SpeedyCGI are that it can only run one program at a time on any particular server interpreter. If the server interpreter is busy processing running one application and receives a request to run another instance of the application or a different application, it has to start a new server interpreter.
JAVA web application servers have attempted to address scalability of JAVA applications. An example of such a server is Inprise Application Server 4. However, such servers only can be invoked from a browser or through a complicated mechanism such as Common Object Request Broker Architecture (CORBA). There is a need for a way to call and interpret source programs from a command line rather than using a browser or mechanism such as CORBA. Web application servers also are typically bulky, require complex installation and are generally very expensive.
Based on the foregoing, there is a need for an improved method of efficiently starting an interpreter for computer programs written in an interpreted language such as JAVA.
There is a specific need for a way to improve the startup efficiency of JAVA interpreted programs that are either started repeatedly and frequently, or consist of small programs, where startup overhead can be greater than the time or resources needed to execute the program itself.
There is a specific need for a method and system that addresses the limitations of SpeedyCGI and JAVA web application servers. For example, there is a need for a way to efficiently interpret computer programs in a way that does not require all elements of the interpreter system to reside or execute on the same machine, to interpret multiple programs at once, and to support command-line invocation of the interpreter system.